using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace MAF.Common
{
    /// <summary>
    /// 词语转换类，协助把词语从一种形式转换成另一种形式
    /// </summary>
    public class WordConverter
    {
        #region 大小写转换
        /// <summary>
        /// 把词语第一个字母变成大写
        /// </summary>
        /// <param name="words"></param>
        /// <returns></returns>
        public static string ToUpperA(string word)
        {
            if (string.IsNullOrEmpty(word)) return "";
            return word.Substring(0, 1).ToUpper() + word.Substring(1);
        }

        /// <summary>
        /// 把单词第一个字母变成小写
        /// </summary>
        /// <param name="words"></param>
        /// <returns></returns>
        public static string ToLowerA(string word)
        {
            if (string.IsNullOrEmpty(word)) return "";
            return word.Substring(0, 1).ToLower() + word.Substring(1);
        }

        #endregion

        #region 单词单复数转换
        /// <summary>
        /// 复数化
        /// </summary>
        /// <param name="words"></param>
        /// <returns></returns>
        public static string Pluralize(string word)
        {
            return WordFormatting.Pluralize(word);
        }
        // 单数化
        public static string Singularize(string word)
        {
            return WordFormatting.Singularize(word);
        }
        // 是否是复数
        public static bool IsPlural(string word)
        {
            return WordFormatting.IsPlural(word);
        }
        #endregion
    }
    
    /// <summary>
    /// 单词单复数转换
    /// </summary>
    internal class WordFormatting
    {
        private static readonly IList<string> Unpluralizables = new List<string>();
        private static readonly IDictionary<string, string> Pluralizations = new Dictionary<string, string>();
        private static readonly IDictionary<string, string> Singularizations = new Dictionary<string, string>();
        static WordFormatting()
        {
            Unpluralizables.Add("equipment");
            Unpluralizables.Add("information");
            Unpluralizables.Add("rice");
            Unpluralizables.Add("money");
            Unpluralizables.Add("species");
            Unpluralizables.Add("series");
            Unpluralizables.Add("fish");
            Unpluralizables.Add("sheep");
            Unpluralizables.Add("deer");
            // Start with the rarest cases, and move to the most common
            Pluralizations.Add("person", "people");
            Pluralizations.Add("ox", "oxen");
            Pluralizations.Add("child", "children");
            Pluralizations.Add("foot", "feet");
            Pluralizations.Add("tooth", "teeth");
            Pluralizations.Add("goose", "geese");
            // And now the more standard rules.
            Pluralizations.Add("(.*)fe?", "$1ves");         // ie, wolf, wife
            Pluralizations.Add("(.*)man$", "$1men");
            Pluralizations.Add("(.+[aeiou]y)$", "$1s");
            Pluralizations.Add("(.+[^aeiou])y$", "$1ies");
            Pluralizations.Add("(.+z)$", "$1zes");
            Pluralizations.Add("([m|l])ouse$", "$1ice");
            Pluralizations.Add("(.+)(e|i)x$", @"$1ices");    // ie, Matrix, Index
            Pluralizations.Add("(octop|vir)us$", "$1i");
            Pluralizations.Add("(.+(s|x|sh|ch))$", @"$1es");
            Pluralizations.Add("(.+)", @"$1s");
            // Start with the rarest cases, and move to the most common
            Singularizations.Add("people", "person");
            Singularizations.Add("oxen", "ox");
            Singularizations.Add("children", "child");
            Singularizations.Add("feet", "foot");
            Singularizations.Add("teeth", "tooth");
            Singularizations.Add("geese", "goose");
            // And now the more standard rules.
            Singularizations.Add("(.*)ives?", "$1ife");
            Singularizations.Add("(.*)ves?", "$1f"); // ie, wolf, wife
            Singularizations.Add("(.*)men$", "$1man");
            Singularizations.Add("(.+[aeiou])ys$", "$1y");
            Singularizations.Add("(.+[^aeiou])ies$", "$1y");
            Singularizations.Add("(.+)zes$", "$1");
            Singularizations.Add("([m|l])ice$", "$1ouse");
            Singularizations.Add("matrices", @"matrix");
            Singularizations.Add("indices", @"index");
            Singularizations.Add("(.*)ices", @"$1ex");  // ie, Matrix, Index
            Singularizations.Add("(octop|vir)i$", "$1us");
            Singularizations.Add("(.+(s|x|sh|ch))es$", @"$1");
            Singularizations.Add("(.+)s$", @"$1");
        }
        // 转换为复数
        public static string Pluralize(string word)
        {
            if (Unpluralizables.Contains(word) || true == IsPlural(word))
                return word;

            string plural = "";
            foreach (KeyValuePair<string, string> pluralization in Pluralizations)
            {
                if (Regex.IsMatch(word, pluralization.Key))
                {
                    plural = Regex.Replace(word, pluralization.Key, pluralization.Value);
                    break;
                }
            }
            return plural;
        }
        // 转换为单数
        public static string Singularize(string word)
        {
            if (Unpluralizables.Contains(word.ToLowerInvariant()) || false == IsPlural(word))
                return word;

            foreach (KeyValuePair<string, string> singularization in Singularizations)
            {
                if (Regex.IsMatch(word, singularization.Key))
                {
                    return Regex.Replace(word, singularization.Key, singularization.Value);
                }
            }
            return word;
        }
        // 是否是复数
        public static bool IsPlural(string word)
        {
            if (Unpluralizables.Contains(word.ToLowerInvariant()))
            {
                return true;
            }
            foreach (KeyValuePair<string, string> singularization in Singularizations)
            {
                if (Regex.IsMatch(word, singularization.Key))
                {
                    return true;
                }
            }
            return false;
        }
    }
}